﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wicture.DbRESTFul.Cache;
using Wicture.QPZS.EPC.API.Domain;
using Wicture.QPZS.EPC.API.Domain.Entities;

namespace Wicture.QPZS.EPC.API.Throttlings
{
    public abstract class FrequencyThrotting : IThrottling
    {
        private readonly ICacheProvider _cacheProvider = CacheProviderFactory.CacheProviders.Values.FirstOrDefault();
        public const int ExpirationInSeconds = 60;

        public abstract decimal Order { get; }

        public List<ServicePackageType> ServicePackageTypes => new List<ServicePackageType> {
            ServicePackageType.包时,
            ServicePackageType.包次,
            ServicePackageType.计价
        };

        public virtual void Invoke(ThrottlingContext context)
        {
            if (!NeedFrequency(context))
            {
                return;
            }
            var invocationFrequency = GetInvocationFrequency(context);
            SetFrequency(context, invocationFrequency);
            var frequencyKey = BuildFrequencyKey(context.AccountId.ToString());
            _cacheProvider.Set(frequencyKey, invocationFrequency, ExpirationInSeconds);
        }

        protected abstract void SetFrequency(ThrottlingContext context, InvocationFrequency invocationFrequency);

        protected virtual bool NeedFrequency(ThrottlingContext context)
        {
            return true;
        }

        protected virtual InvocationFrequency GetInvocationFrequency(ThrottlingContext context)
        {
            var frequencyKey = BuildFrequencyKey(context.AccountId.ToString());
            var invocationFrequency = _cacheProvider.Get(frequencyKey)?.ToObject<InvocationFrequency>();

            if (invocationFrequency == null)
            {
                invocationFrequency = new InvocationFrequency { ApiCounters = new List<ApiCounter>(), Stamp = DateTime.UtcNow };
            }
            else
            {
                var expired = DateTime.UtcNow - invocationFrequency.Stamp > TimeSpan.FromSeconds(ExpirationInSeconds);
                if (expired)
                {
                    invocationFrequency = new InvocationFrequency { ApiCounters = new List<ApiCounter>(), Stamp = DateTime.UtcNow };
                }
            }
            return invocationFrequency;
        }

        private string BuildFrequencyKey(string id)
        {
            return $"API_{id}";
        }
    }
}
